/*************************************************************************
 *
 * funkce pro praci s casem ve formatu ala-unix
 * 
 * (c) Ales Povalac, alpov@alpov.net, http://www.alpov.net/
 * 
 *************************************************************************
 *
 * $Id: datetime.c 32 2006-06-30 15:46:46Z alpov $
 * 
 *************************************************************************/         

#include <avr/pgmspace.h>
#include "datetime.h"

unsigned char PROGMEM month_days[2][12] = {
    {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};


/*************************************************************************
 * casova cast promenne datetime
 *************************************************************************/ 
unsigned long time_of(unsigned long datetime)
{
    return datetime % 86400;
}


/*************************************************************************
 * datova cast promenne datetime
 *************************************************************************/ 
unsigned long date_of(unsigned long datetime)
{
    return datetime / 86400;
}
 

/*************************************************************************
 * vytvoreni promenne datetime
 *************************************************************************/ 
unsigned long encode_datetime(unsigned char year, unsigned char month, \
    unsigned char day, unsigned char hour, unsigned char min, unsigned char sec)
{
    unsigned int day_c = day - 1;
    
    month--;
    while (month--)
        day_c += pgm_read_byte(&month_days[__isleap(year)][month]);

    while (year--)
        day_c += __isleap(year) ? 366 : 365;
    
    return ((((unsigned long)day_c * 24 + hour) * 60 + min) * 60 + sec);
}


/*************************************************************************
 * ziskani casu z promenne datetime
 *************************************************************************/ 
void decode_time(unsigned long datetime, unsigned char *hour, \
    unsigned char *min, unsigned char *sec)
{
    unsigned long time = time_of(datetime);

    *sec = time % 60;
    time /= 60;

    *min = time % 60;
    time /= 60;

    *hour = time;
}


/*************************************************************************
 * ziskani dne v tydnu z promenne datetime
 * 0 = pondeli ... 6 = nedele 
 *************************************************************************/ 
unsigned char day_of_week(unsigned long datetime)
{
    return (date_of(datetime) + 5) % 7;
}


/*************************************************************************
 * ziskani datumu z promenne datetime
 *************************************************************************/ 
void decode_date(unsigned long datetime, unsigned char *year, \
    unsigned char *month, unsigned char *day)
{
    unsigned long date = date_of(datetime);
    unsigned int i;

    *year = 0;
    *month = 1;

    while (date >= (i = __isleap(*year) ? 366 : 365)) {
        (*year)++;
        date -= i;
    }
    
    while (date >= (i = pgm_read_byte(&month_days[__isleap(*year)][*month - 1]))) {
        (*month)++;
        date -= i;
    }
    
    *day = date + 1;
}
